/*
 * Histgram.h
 *
 *  Created on: May 29, 2012
 *      Author: marchi
 */

#ifndef HISTOGRAM_H_
#define HISTOGRAM_H_
#include <vector>
#include <ostream>
#include <iomanip>
#include <iostream>
#include <cmath>
#include <numeric>
#include <algorithm>

using std::vector;
using std::cout;
using std::endl;
using std::accumulate;

namespace Histogram_NS {
class op_multiply{
	double mult;
public:
	op_multiply():mult(1.0){};
	op_multiply(double x):mult(x){};
	double operator()(double x){return x*mult;}
};
class Point2D{
	double x,y;
public:
	Point2D():x(0),y(0){};
	Point2D(double o,double p):x(o),y(p){};
	Point2D & operator()(double o, double p){x=o;y=p;return *this;}
};
class Histogram {
	double dx;
	double xmin,xmax;
	unsigned int length;
	vector<double> hg;
	void init(){
		length=static_cast<int> (ceil((xmax-xmin)/dx+1));
		hg=vector<double>(length,0.0);
	}
public:
	Histogram():dx(0.005),xmin(0.0),xmax(0.6){init();};
	Histogram(double t_dx,double t_min, double t_max): dx(t_dx),xmin(t_min),xmax(t_max){init();};
	Histogram & operator()(double t){
		unsigned int nx=(t>xmax)?length:(t<xmin)?0:static_cast<int> (ceil((t-xmin)/dx));
		hg[nx]+=1.0;
		return *this;
	}
	void setdx(double t_dx){dx=t_dx;}
	void setMin(double t_min){xmin=t_min;}
	void setMax(double t_max){xmax=t_max;}
	vector<double> & gHG(){return hg;}
	void sHG(vector<double>::iterator & it){for(unsigned int n=0;n<length;n++) hg[n]=*(it++);}

	void Avg(){
		double tot=dx*accumulate(hg.begin(),hg.end(),0.0);
		if(tot != 0.0) std::transform(hg.begin(),hg.end(),hg.begin(),op_multiply(1.0/tot));
	}
	vector<Point2D>  copyPoints(){
		vector<Point2D> tm;
		for(unsigned int n=0;n<length;n++){
			double x=xmin+dx*n;
			double y=hg[n];
			tm.push_back(Point2D(x,y));
		}
		return tm;
	}

	double TotHist(){return accumulate(hg.begin(),hg.end(),0.0);}
	friend std::ostream & operator<<(std::ostream & fout, Histogram & o){
		for(unsigned int n=0;n<o.length;n++){
			double x=o.xmin+o.dx*n;
			double y=o.hg[n];
			fout << std::fixed << std::setw(11) << std::right << x << " ";
			fout << std::fixed << std::setw(11) << std::right << y << " ";
			fout << endl;
		}
		return fout;
	}
	unsigned int gLength(){return length;}
	virtual ~Histogram();
};

} /* namespace Histogram_NS */
#endif /* HISTGRAM_H_ */
